﻿//-----------------------------------------------------------------------
// <copyright file="WindowsImpersonationManager.cs" company="tuliprules.org">
//     Copyright (c) 2010 tuplelister, tuliprules.org.
// </copyright>
// <summary>This is the WindowsImpersonationManager class.</summary>
//-----------------------------------------------------------------------

namespace Tulip.Rules
{
    using System;
    using System.Globalization;
    using System.Security.Principal;

    /// <summary>
    /// Manages impersonation of a given WindowsIdentity
    /// </summary>
    internal class WindowsImpersonationManager : IDisposable
    {
        /// <summary>
        /// The Windows impersonation context used during impersonation.
        /// </summary>
        private readonly WindowsImpersonationContext windowsImpersonationContext;

        /// <summary>
        /// Initializes a new instance of the WindowsImpersonationManager class.
        /// </summary>
        /// <param name="windowsIdentity">
        /// The Windows identity that will be impersonated.
        /// </param>
        public WindowsImpersonationManager(WindowsIdentity windowsIdentity)
        {
            if (windowsIdentity == WindowsIdentity.GetCurrent() || windowsIdentity == null)
            {
                return;
            }

            try
            {
                this.windowsImpersonationContext = windowsIdentity.Impersonate();
            }
            catch (InvalidOperationException)
            {
                throw new RulesException(Properties.Resources.ExAnonUserImpersonation);
            }
            catch (Exception ex)
            {
                throw new RulesException(string.Format(CultureInfo.CurrentCulture, Properties.Resources.ExImpersonationFailed, windowsIdentity.Name, ex.Message), ex);
            }
        }

        /// <summary>
        /// Finalizes an instance of the <see cref="WindowsImpersonationManager"/> class. 
        /// </summary>
        ~WindowsImpersonationManager()
        {
            Dispose(false);
        }

        /// <summary>
        /// Disposes the WindowsImpersonationManager class.  Reverts back to the original
        /// Windows identity prior to impersonation.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Manages disposal internally.  If called by the finalizer, no reversion is undertaken.
        /// To revert, the Dispose() method must be called explicitly or via the using statement (C#).
        /// </summary>
        /// <param name="disposing">
        /// Indicates whether the instance is being disposed explicitly througha call to the Dispose 
        /// method.
        /// </param>
        protected virtual void Dispose(bool disposing)
        {
            if (this.windowsImpersonationContext == null || !disposing)
            {
                return;
            }

            this.windowsImpersonationContext.Undo();
            this.windowsImpersonationContext.Dispose();
        }
    }
}